# -*- coding: utf-8 -*-
"""A Namespace describes a QPBuild Namespace. These entities are created by
polling the namespace server(s) and merging the results into the database.
"""

from sqlalchemy import *
from sqlalchemy.orm import mapper, relation
from sqlalchemy import Table, ForeignKey, Column
from sqlalchemy.types import Integer, Unicode

from abserver.model import DeclarativeBase, metadata, DBSession


class BuilderSchedule(DeclarativeBase):
    # table options
    __tablename__ = 'builderschedule'

    # columns
    schedule_id = Column(Integer, primary_key=True, autoincrement=True)
    schedule_enabled = Column(Boolean)
    schedule_one_off = Column(Boolean)

    schedule_builder_id = Column(Integer, ForeignKey('builder.builder_id'))
    schedule_branch_id = Column(Integer, ForeignKey('branch.branch_id'))
    schedule_product_id = Column(Integer, ForeignKey('product.product_id'))

    # relationships
    schedule_builder = relation('Builder', backref='builderschedules')
    schedule_branch = relation('Branch', backref='builderschedules')
    schedule_product = relation('Product', backref='builderschedules')

    def __init__(self, builder, product, branch):
        self.schedule_builder = builder
        self.schedule_product = product
        self.schedule_branch = branch
        self.schedule_enabled = True
        self.schedule_one_off = False
##        self.flush() # flush to get the schedule_id allocated

    @classmethod
    def get_schedule(cls, builder, product, branch):
        schedules = DBSession.query(cls).filter(cls.schedule_builder == builder).all()
        if not schedules:
            schedule = cls(builder, product, branch)
            DBSession.add(schedule)
        else:
            schedule = schedules[-1]
        return schedule

    @staticmethod
    def fetch_schedule(cls, builder_name):
        builder = Builder.get_builder(builder_name)
        schedules = DBSession.query(cls).filder(cls.schedule_builder == builder).first()
        if schedules:
            # return the _last_ schedule so that temporary overrides can be created
            # and then deleted.
            schedule = schedules[-1]
            # make sure we get the latest version of this object. The SQLAlchemy ORM
            # caches this object for us.
            DBSession.refresh(schedule)
            if schedule.schedule_enabled:
                if schedule.schedule_one_off:
                    # this has been configured as a one-off schedule, so disable
                    # it because a request has been made.
                    schedule.schedule_enabled = False
                return schedule.product.component.component_name, schedule.branch.branch_name
            else:
                return "", ""
        return None
        
class Builder(DeclarativeBase):
    """This class describes a builder server. One of these will be
    created for each new builder that is contributing builds to the
    warehouse.
    """
    # table options
    __tablename__ = 'builder'

    # columns
    builder_id = Column(Integer, primary_key=True, autoincrement=True)
    builder_name = Column(Unicode(64), nullable=False, unique=True)
    builder_description = Column(Unicode()) # wiki markup
    builder_location = Column(Unicode())

    # relationships
    ## builds
    ## builderschedules

    def __init__(self, builder_name, builder_description=None, builder_location=None):
        self.builder_name = builder_name
        self.builder_description = builder_description
        self.builder_location = builder_location

    @classmethod
    def get_builder(cls, builder_name, builder_description=None, builder_location=None):
        builder = DBSession.query(cls).filter(cls.builder_name==builder_name).first()
        if not builder:
            builder = cls(builder_name, builder_description, builder_location)
            DBSession.add(builder)
        return builder

    @classmethod
    def get_builder_listing(cls):
        builders = cls.query.all()
        return [ (b.builder_id, b.builder_name) for b in builders ]

